/*********************************************************************************************************
**
**                                   GJB 标准测试集
**
**                               Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文   件   名: gjb_S0102606AQ_addr_nonalign.c
**
** 文件创建日期: 2021 年 1 月 12 日
**
** 描        述: 通过构造地址非对齐异常验证操作系统的异常处理功能
*********************************************************************************************************/
#ifdef SYLIXOS
#define __SYLIXOS_KERNEL
#endif
#include <pthread.h>
#include <stdio.h>
#include <errno.h>
#include <setjmp.h>
// #include "gjb.h"

static pthread_attr_t  thread_attr3;
static pthread_t       thread_id3;
static int             exec_flags = 0;




typedef unsigned int u32;
typedef u32      		ARCH_REG_T;
typedef struct {
    ARCH_REG_T      REG_uiCpsr;
    ARCH_REG_T      REG_uiR14;
    ARCH_REG_T      REG_uiR13;
    ARCH_REG_T      REG_uiR0;
    ARCH_REG_T      REG_uiR1;
    ARCH_REG_T      REG_uiR2;
    ARCH_REG_T      REG_uiR3;
    ARCH_REG_T      REG_uiR4;
    ARCH_REG_T      REG_uiR5;
    ARCH_REG_T      REG_uiR6;
    ARCH_REG_T      REG_uiR7;
    ARCH_REG_T      REG_uiR8;
    ARCH_REG_T      REG_uiR9;
    ARCH_REG_T      REG_uiR10;
    ARCH_REG_T      REG_uiR11;
    ARCH_REG_T      REG_uiR12;
    ARCH_REG_T      REG_uiR15;
    ARCH_REG_T	     REG_ulCP0Epc;
    ARCH_REG_T      REG_ulPc;
    ARCH_REG_T REG_XIP;

#define REG_uiFp    REG_uiR11
#define REG_uiIp    REG_uiR12
#define REG_uiSp    REG_uiR13
#define REG_uiLr    REG_uiR14
#define REG_uiPc    REG_uiR15
} ARCH_REG_CTX;
typedef ARCH_REG_CTX REG_SET;
typedef void (*EXC_HANDLER) (int,  REG_SET* );
EXC_HANDLER user_handler = NULL;
jmp_buf EXCEPTION_ENV_MASK;
REG_SET no_use_reg;
EXC_HANDLER exception_handler_set(EXC_HANDLER handler);


#define gjb_os_printk                   gjb_printk
#define gjb_printk(fmt, arg...)      ({_PrintFormat(fmt, ##arg); _PrintFormat("\r\n");})

#define gjb_os_pc_resume                gjb_pc_resume
void gjb_pc_resume (REG_SET* reg)
{
#if defined(__aarch64__)
    reg->REG_ulPc += 8;
#endif

#if defined(__mips64)
    reg->REG_ulCP0Epc += 8;
#endif

#if defined(__mips__)
    reg->REG_ulCP0Epc += 4;
#endif

#if defined(__loongarch64)
    reg->REG_ulCP0Epc += 4;
#endif

#if defined(__arm__)
    reg->REG_uiPc += 4;
#endif

#if defined(__i386__)
    reg->REG_XIP += 4;
#endif

#if defined(__x86_64__)
    reg->REG_XIP += 8;
#endif
}

#define gjb_os_address_noalign          gjb_address_noalign
static inline void gjb_address_noalign (void)
{
#ifdef __arm__
    long  a = 0x123456;

    *(int *)(a + 1) = 12;
#endif

#if defined(__x86_64__) || (__i386__)
    long  p = 0x0;
    *(int *)p = 1;
#endif

#ifdef __aarch64__
    struct foo x = {{0, 1, 2, 3, 4, 5, 6, 7}};
    atomic_t *v = (atomic_t *)(x.bar + 3);

    LONG lOld = 0;
    LONG lNew = 1;
    LONG lTemp;
    LONG lOldVal;

    __asm__ __volatile__(
        "MRS %[tmp], SCTLR_EL1\n"
        "ORR %[tmp], %[tmp], #(1 << 1)\n"
        "MSR SCTLR_EL1, %[tmp]\n"
        "ldxr %w[oldval], %[v] \n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        :[tmp] "=&r" (lTemp),[oldval] "=&r" (lOldVal), [v] "+Q"(v->counter)
        :[old]"Lr"(lOld),[new]"r"(lNew)
        :"memory"
    );
#endif

#if defined(__loongarch64) || defined(__mips__)
    struct foo x = {{0, 1, 2, 3, 4, 5, 6, 7}};

    unsigned int *p = (unsigned int *)(x.bar + 3);

    long          p1 = 0x0;

    *(int *)p1       = 1;

    *p = 0xdeadface;

    __asm__("nop");
    __asm__("nop");
    __asm__("nop");
    __asm__("nop");
    __asm__("nop");
    __asm__("nop");
    __asm__("nop");
    __asm__("nop");

    p = (unsigned int *)x.bar;

    *p = 1;
#endif
}
#define _PrintFormat printf
int pthread_delay(int ticks);

void ExFunsecurity(int exc, REG_SET* reg)
{
    gjb_os_printk("excFun is running\n");
    exec_flags++;
    /*
     *  发生异常后, 使PC寄存器指向下一条正常指令
     */
    gjb_os_pc_resume(reg);

    gjb_os_printk("excFun is running over\n");
}


void *Fun3_security_4 (void *arg)
{
    printf("Task3 is running-1\n");

    /*
     *  构造地址非对齐异常, 不同的平台该函数的实现不同
     */
    gjb_os_address_noalign();
    printf("Task3 is running-2\n");

    return NULL;
}
//地址对齐异常测试入口函数
int Test_S0102105AQ3 (void)
{
    int          status = -100;
    int          nDelaytime = 2000;
    int          i = 0;
    EXC_HANDLER  old;

    /*
     *  注册一个用户异常处理函数
     */
    old = exception_handler_set((EXC_HANDLER)ExFunsecurity);

    printf("exception_handler_set status = %x\n", (unsigned int)(long)old);

    //创建任务
    pthread_attr_init(&thread_attr3);

    // thread_attr3.stackaddr = NULL;
    // thread_attr3.stacksize = PTHREAD_STACK_MIN * 2;
    // thread_attr3.inheritsched = PTHREAD_EXPLICIT_SCHED;
    // thread_attr3.schedpolicy = SCHED_FIFO;
    // thread_attr3.schedparam.sched_priority = 100;
    // thread_attr3.name = "Task3";

    status = pthread_create(&thread_id3, &thread_attr3, Fun3_security_4, NULL);
    if (status == 0) {
        printf( "Task3 Create succesful\n");

    } else {
        printf( "Task3 Create Failed\n");
        return  (-1);
    }

    pthread_delay(nDelaytime);      // 2000��ticks

    for (i = 0; i < 10; i++) {
        printf("MainFun is running\n");
    }

 /*
     *  恢复用户异常处理函数
     */
    exception_handler_set(NULL);    // 只是恢复一下之前的环境

    if (!exec_flags) {
        return  (-1);
    }

    return  (0);
}
/**********************************************************************
 * 函数名称： GJB_ENTRY()
 * 功能描述： 用户程序入口
 * 输入参数： 无
 * 输出参数： 无
 * 返 回 值： 无
 * 其它说明： 无
 **************************************************************************/
int main(int argc, char **argv)
{
    int  result;

    result = Test_S0102105AQ3();    /* exec test  */
    if (result != 0) {
        return (-1);
    }

    return (0);
}

typedef unsigned long long u64;
typedef	unsigned int 	u32;
#define SYSTEM_TICKS_USEC        1000

u64 g_pthread_delay_tick = 0;
int is_set_sys_rate = 0;
u32 g_sys_uleep_tick = 0;
int pthread_delay(int ticks)
{
    g_pthread_delay_tick = ticks;
    sched_yield();
    if(is_set_sys_rate)
    {
        return usleep(g_sys_uleep_tick * ticks);
    }
    else
    {
        return usleep(SYSTEM_TICKS_USEC * ticks);
    }
}
void signal_handler_fun(int signum)
{
    // printf("catch signal %d\n", signum);
    errno = EINVAL;
    if(user_handler != NULL)
    {
        user_handler(signum, &no_use_reg);
    }
    siglongjmp(EXCEPTION_ENV_MASK, 1);
}
EXC_HANDLER exception_handler_set(EXC_HANDLER handler)
{
    #define	SIGSEGV		11	/* Invalid access to storage.  */
    #define SIGBUS		10	/* Bus error.  */
    #define	SIGTERM		15	/* Termination request.  */
    #define	SIGILL		4	/* Illegal instruction.  */
    signal(SIGSEGV, signal_handler_fun);
    signal(SIGBUS, signal_handler_fun);
    signal(SIGTERM, signal_handler_fun);
    signal(SIGILL, signal_handler_fun);
    
    //    signal(SIGUSR1, signal_handler_fun);
    //    signal(SIGUSR1, signal_handler_fun);
    //    signal(SIGUSR1, signal_handler_fun);
    user_handler = handler;
    return handler;
}